package com.dnjn.mes.biz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dnjn.mes.biz.Const;
import com.dnjn.mes.biz.assist.ext.Wrapperz;
import com.dnjn.mes.biz.domain.*;
import com.dnjn.mes.biz.enums.BoolType;
import com.dnjn.mes.biz.enums.MaintainType;
import com.dnjn.mes.biz.enums.MessageType;
import com.dnjn.mes.biz.mapper.MesWorkpieceMapper;
import com.dnjn.mes.biz.service.*;
import com.dnjn.mes.common.utils.JpPinyinUtil;
import com.dnjn.mes.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 工件 零部件 服务实现类
 * </p>
 *
 * @author Amber
 * @since 2023-07-26
 */
@Service
public class MesWorkpieceServiceImpl extends ServiceImpl<MesWorkpieceMapper, MesWorkpiece> implements IMesWorkpieceService {

    @Autowired
    private IMesResolvePlanService planService;

    @Autowired
    private IMesExceptPlanXrefService mesExceptPlanXrefService;

    @Autowired
    private IMesMessageService messageService;

    @Autowired
    private IMesEquipmentService equipmentService;
    @Autowired
    private IMesAssemblyService assemblyService;
    @Autowired
    private IMesRecordMaintainService recordMaintainService;
    @Override
    public String importData(List<MesWorkpiece> list, boolean updateSupport) throws Exception {
        //获取当前机器
        String equipmentNameIn = list.get(0).getEquipmentName();
        MesEquipment mesEquipment = equipmentService.getOne(Wrapperz.lambdaQuery(MesEquipment.class).eq(MesEquipment::getEquipmentName, equipmentNameIn));
        if (null == mesEquipment) {
            throw new Exception("机器为空,查询失败!" + equipmentNameIn);
        }
        Integer workOrdinal = getMaxOrdinal();
        for (MesWorkpiece domain : list) {
            String workpieceName = StringUtils.trimStr(domain.getWorkpieceName());

            domain.setWorkpieceName(workpieceName);
            String assemblyName = StringUtils.trimStr(domain.getAssemblyName());
            domain.setAssemblyName(assemblyName);
//                long count = baseMapper.selectCount(
//                        Wrappers.<MesWorkpiece>lambdaQuery().eq(MesWorkpiece::getWorkpieceName, domain.getWorkpieceName()).eq(MesWorkpiece::getAssemblyId,one.getAssemblyId()));
            long count = baseMapper.queryByName(domain.getWorkpieceName(), domain.getAssemblyName());
            if (count > 0) {
                continue;//todo
            }

            String equipmentName = mesEquipment.getEquipmentName();
//            String substring = equipmentName.substring(0,2);
            int start = equipmentName.length() - 3, end = equipmentName.length() - 1;
            start = Math.max(start, 0);

            String substring = equipmentName.substring(start, end);
            String pinYin = JpPinyinUtil.changeToTonePinYin(substring);
            //domain.setWorkpieceNamePinyin(pinYin);
            //处理图片/步骤    media/paiban/image/2.pngme
            domain.setWorkpieceImage("media/" + pinYin + "/image/" + domain.getWorkpieceImage());
            domain.setMaintainStepUrl("media/" + pinYin + "/docs/" + domain.getMaintainStepUrl());
            //处理模块id,如果有模块就关联,没有就新增模块

            MesAssembly assembly = assemblyService.getOne(Wrapperz.lambdaQuery(MesAssembly.class).eq(MesAssembly::getEquipmentId, mesEquipment.getEquipmentId()).eq(MesAssembly::getAssemblyName, domain.getAssemblyName()));
            if (null == assembly) {
                MesAssembly mesAssembly = new MesAssembly();
                mesAssembly.setAssemblyName(domain.getAssemblyName());
                mesAssembly.setEquipmentId(mesEquipment.getEquipmentId());
                Integer assemblyOrdinal = assemblyService.getMaxOrdinal();
                assemblyOrdinal++;
                mesAssembly.setOrdinal(assemblyOrdinal);
                assemblyService.save(mesAssembly);
                Long assemblyId = assemblyService.getOne(Wrapperz.lambdaQuery(MesAssembly.class).
                        eq(MesAssembly::getEquipmentId, mesEquipment.getEquipmentId()).eq(MesAssembly::getAssemblyName, domain.getAssemblyName())).getAssemblyId();
                domain.setAssemblyId(assemblyId);

            } else {
                domain.setAssemblyId(assembly.getAssemblyId());
            }
            //domain.setCreateBy(operName);
            //domain.setAssemblyId(assemblyId);//todo
            domain.setLastMaintainTime(LocalDateTime.now());//?
            domain.setTimeSpent(BigDecimal.ZERO);
            workOrdinal++;
            domain.setOrdinal(workOrdinal);
            domain.setEquipmentId(mesEquipment.getEquipmentId());
            save(domain);
        }
        return "OK";
    }

    @Override
    public MesWorkpiece selectByWorkpieceName(Long assemblyId, String workpieceName) {
        return lambdaQuery().eq(MesWorkpiece::getAssemblyId, assemblyId)
                .eq(MesWorkpiece::getWorkpieceName, workpieceName)
                .one();
    }

    @Override
    public MesWorkpiece queryBy(String equipmentName, String assemblyName, String workpieceName) {

        return baseMapper.queryBy(equipmentName, assemblyName, workpieceName);
    }

    @Override
    public List<MesWorkpiece> selectWorkList(MesWorkpiece domain) {
        return baseMapper.selectWorkList(domain);
    }

    @Override
    public void updateTimeSpentByMaintainType(double durationHour, MaintainType maintainType) {
        baseMapper.updateTimeSpentByMaintainType(durationHour, maintainType.getCode());
    }

    @Override
    @Transactional
    public Long removeWorkById(Long workpieceId) {
        //删除联动数据
        /*QueryWrapper<MesResolvePlan> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("workpiece_id",workpieceId);
        List<MesResolvePlan> resolvePlans = planService.list(queryWrapper);
        List<Long> planIdList = resolvePlans.stream().filter(r -> r.getWorkpieceId().equals(workpieceId)).map(MesResolvePlan::getPlanId).collect(Collectors.toList());
        if (!planIdList.isEmpty()) {
            for (Long planId : planIdList) {
                //删除方案异常关联表
                mesExceptPlanXrefService.removeByPlanId(planId);
                //删除工件关联方案
                planService.removePlanById(planId);

            }
        }*/
        //软删除工件
        return baseMapper.deleteWorkById(workpieceId);
    }

    @Override
    public List<MesWorkpiece> searchWorkByName(String searchKey, Long assemblyId) {
        List<MesWorkpiece> workpieceList = baseMapper.searchWorkByName(searchKey, assemblyId);
        BigDecimal warnBigDecimal = BigDecimal.valueOf(10);//警告标记
        BigDecimal remindBigDecimal = BigDecimal.valueOf(30);//提醒标记
        BigDecimal bigDecimal = BigDecimal.valueOf(100);

        for (MesWorkpiece mesWorkpiece : workpieceList) {
            //计算寿命百分比   time_spent/maintain_duration
            BigDecimal timeSpent = mesWorkpiece.getTimeSpent();//耗时
            Integer maintainDuration = mesWorkpiece.getMaintainDuration();//保养周期寿命
            BigDecimal multiply = timeSpent.divide(BigDecimal.valueOf(maintainDuration), RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
            //用100-耗时所占百分比，就是剩余寿命百分比
            multiply = bigDecimal.subtract(multiply);
            if (multiply.compareTo(warnBigDecimal) <= 0) {// <0 小于 | = 0 等于 | >0 大于
                mesWorkpiece.setStatus(0);//警告
            } else if (multiply.compareTo(warnBigDecimal) > 0 && multiply.compareTo(remindBigDecimal) <= 0) {//大于10 小于30 提醒
                mesWorkpiece.setStatus(1);//提醒
            } else {
                mesWorkpiece.setStatus(2);//正常
            }
        }

        return workpieceList;
    }

    @Override
    public MesWorkpiece maintenanceCountdown(Long equipmentId) {
        List<MesWorkpiece> workpieceList = baseMapper.maintenanceCountdown(equipmentId);
        Optional<MesWorkpiece> min = workpieceList.stream().min(Comparator.comparingInt(MesWorkpiece::getMaintainDuration));
        return min.get();
    }

    @Override
    @Transactional
    public boolean maintenanceWork(Long workpieceId) {
        try {
            baseMapper.maintenanceWork(workpieceId);
            MesMessage mesMessage = new MesMessage();
            mesMessage.setWorkpieceId(workpieceId);
            messageService.updateStatus(mesMessage);
            //新增一条留痕记录到 mes_record_maintain 保养记录表
            MesRecordMaintain mesRecordMaintain = new MesRecordMaintain();
            mesRecordMaintain.setWorkpieceId(workpieceId);
            mesRecordMaintain.setMaintainDatetime(LocalDateTime.now());
            recordMaintainService.save(mesRecordMaintain);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    @Override
    public void handleWorkpiceTask() {
        //监听工件状态，判断状态写入message表记录
        //根据当前设备查询当前设备下的所有工件
        MesEquipment mesEquipment = equipmentService.fetchCurrent();
        List<MesWorkpiece> workpieceList = baseMapper.selectListByEquipmentId(mesEquipment.getEquipmentId());
        BigDecimal warnBigDecimal = BigDecimal.valueOf(10);//警告标记
        BigDecimal remindBigDecimal = BigDecimal.valueOf(30);//提醒标记
        BigDecimal bigDecimal = BigDecimal.valueOf(100);
        for (MesWorkpiece mesWorkpiece : workpieceList) {
            int flag = 2;//标识
            //计算寿命百分比   time_spent/maintain_duration
            BigDecimal timeSpent = mesWorkpiece.getTimeSpent();//耗时
            Integer maintainDuration = mesWorkpiece.getMaintainDuration();//保养周期寿命
            BigDecimal multiply = timeSpent.divide(BigDecimal.valueOf(maintainDuration), RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
            //用100-耗时所占百分比，就是剩余寿命百分比
            multiply = bigDecimal.subtract(multiply);
            if (multiply.compareTo(warnBigDecimal) > 0 && multiply.compareTo(remindBigDecimal) <= 0) {//大于10 小于30 提醒
                flag = 1; //提醒
            }
            if (multiply.compareTo(warnBigDecimal) <= 0) {// <0 小于 | = 0 等于 | >0 大于
                flag = 0;//警告
            }
            if (flag < 1 ) {//警告
                //根据工件id，警告信息，状态为1-未处理的查询是否有数据
                Long count = messageService.lambdaQuery().eq(MesMessage::getWorkpieceId, mesWorkpiece.getWorkpieceId())
                        .eq(MesMessage::getMessageCn, mesWorkpiece.getWarningMessage()).eq(MesMessage::getMessageStatus, Const.YES).count();
                if (count == 0){//不存在时，新增
                    MesMessage msg = new MesMessage()
                            .setMessageStatus(Const.YES)
                            .setMessageType(MessageType.WORKPIECE_MAINTAIN)
                            .setMessageCn(mesWorkpiece.getWarningMessage())
                            .setStartDatetime(LocalDateTime.now())
                            .setExceptId(null)
                            .setEquipmentId(mesEquipment.getEquipmentId())
                            .setWorkpieceId(mesWorkpiece.getWorkpieceId());
                    messageService.save(msg);
                }
            }
            if (flag == 1) {//提醒
                //根据工件id，提醒信息，状态为1-未处理的查询是否有数据
                Long count = messageService.lambdaQuery().eq(MesMessage::getWorkpieceId, mesWorkpiece.getWorkpieceId())
                        .eq(MesMessage::getMessageCn, mesWorkpiece.getRemindMessage()).eq(MesMessage::getMessageStatus, Const.YES).count();
                if(count == 0 ){
                    MesMessage msg = new MesMessage()
                            .setMessageStatus(Const.YES)
                            .setMessageType(MessageType.WORKPIECE_MAINTAIN)
                            .setMessageCn(mesWorkpiece.getRemindMessage())
                            .setStartDatetime(LocalDateTime.now())
                            .setExceptId(null)
                            .setEquipmentId(mesEquipment.getEquipmentId())
                            .setWorkpieceId(mesWorkpiece.getWorkpieceId());
                    messageService.save(msg);
                }
            }
        }


    }

    @Override
    public Integer getMaxOrdinal() {
        Integer rodinal = 0;
        Integer maxOrdinal = baseMapper.getMaxOrdinal();
        if (!Objects.isNull(maxOrdinal)) {
            rodinal = maxOrdinal;
        }
        return rodinal;
    }
}
